#pragma once
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <unistd.h>
#include <vector>
#include <pthread.h>
#include "sem.hpp"
#include "mutex.hpp"
using namespace std;
const int N = 5;
template <typename T>
class singqueue
{
public:
    singqueue(int cap = N) : _sq(cap), _cap(cap)
                     , _datasem(0), _blocksem(cap),
                     _cstep(0),_pstep(0) { }
    void equeue(T& data){
        //现申请信号量再申请锁：高效率：比如人们都先买好票然后再去排队就不用
        //一个人排个队买个票重复了
       _blocksem.P();//申请空格信号量--
       {
       mutexguard md(_p);
       _sq[_pstep++]=data;
       _pstep%=_cap;
       }
       _datasem.V();//放入数据后增加数据信号量

    }
    T& pop(){
        static T out;//防止局部变量销毁
        _datasem.P();//--
        {
        mutexguard md(_c);
        out=_sq[_cstep++];
        _cstep%=_cap;
        }
        _blocksem.V();//++
        return out;
    }

    ~singqueue()   { }

private:
    vector<T> _sq;
    int _cap;
    // 共享资源中管理分块的信号量
    Sem _datasem;
    Sem _blocksem;
    // 消费者生成者之间互斥的锁
    mutex _p;
    mutex _c;
    // 标记当前访问部分资源的位置：
    int _cstep;
    int _pstep;
};